--- title: "06-Java 深拷贝与浅拷贝" aliases: - "Java 深拷贝与浅拷贝" created: 2025-12-25 --- # Java 深拷贝与浅拷贝 --- ## 一、概念总览 ### **1.1 三种拷贝方式对比** ```mermaid %%{init: { "theme": "base", "themeVariables": { "primaryColor": "#e3f2fd", "primaryTextColor": "#0d47a1", "primaryBorderColor": "#2196f3", "lineColor": "#546e7a", "fontSize": "14px", "tertiaryColor": "#fdfdfd" }, "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true } }}%% graph TB %% 样式定义 classDef refStyle fill:#e3f2fd,stroke:#2196f3,stroke-width:2px,color:#0d47a1; classDef shallowStyle fill:#fff3e0,stroke:#ff9800,stroke-width:2px,color:#e65100; classDef deepStyle fill:#f1f8e9,stroke:#4caf50,stroke-width:2px,color:#1b5e20; classDef titleStyle fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px,color:#333,font-weight:bold; MainTitle(["Java 对象拷贝方式总览"]) subgraph SourceObject ["原始对象 A (Memory Structure)"] A_Data["name = '张三'"] A_Addr["address"] Target[("Address Object: 北京")] A_Addr -- "引用指向" --> Target end subgraph CopyTypes ["三种拷贝机制对比"] direction LR subgraph RefCopy ["引用拷贝 (Reference Copy)"] R1["两个引用指向同一对象"] R2["A == B (地址相同)"] R3["修改 B 会影响 A"] end subgraph ShallowCopy ["浅拷贝 (Shallow Copy)"] S1["创建新对象 B"] S2["基本类型拷贝值"] S3["引用类型共享地址"] end subgraph DeepCopy ["深拷贝 (Deep Copy)"] D1["完全独立的新对象"] D2["递归拷贝所有层级"] D3["修改 B 对 A 无影响"] end end subgraph Comparison ["底层效果直观对比"] C1["B ──┐
     ├─> [同一个对象]
A ──┘"] C2["B (新对象) ──> [共享 Address]
A (原对象) ──> [共享 Address]"] C3["B (新对象) ──> [新 Address]
A (原对象) ──> [原 Address]"] end %% 连接逻辑 MainTitle --> SourceObject SourceObject --> CopyTypes RefCopy ==> C1 ShallowCopy ==> C2 DeepCopy ==> C3 %% 应用样式 class RefCopy,R1,R2,R3,C1 refStyle; class ShallowCopy,S1,S2,S3,C2 shallowStyle; class DeepCopy,D1,D2,D3,C3 deepStyle; class MainTitle titleStyle; class SourceObject,A_Data,A_Addr,Target titleStyle; ``` ### **1.2 一句话定义** | **拷贝类型** | **定义** | **修改影响** | | --- | --- | --- | | **引用拷贝** | 复制引用地址,两个引用指向同一对象 | 完全影响 | | **浅拷贝** | 创建新对象,但内部引用类型属性共享 | 部分影响 | | **深拷贝** | 创建新对象,所有层级都是全新的 | 互不影响 | --- --- ## 二、引用拷贝 ### **2.1 概念图解** ```mermaid %%{init: { "theme": "base", "themeVariables": { "primaryColor": "#e3f2fd", "primaryTextColor": "#0d47a1", "primaryBorderColor": "#2196f3", "lineColor": "#546e7a", "fontSize": "14px", "tertiaryColor": "#f5f5f5" }, "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true } }}%% flowchart LR %% 样式定义 classDef stackStyle fill:#e3f2fd,stroke:#2196f3,stroke-width:2px,color:#0d47a1; classDef heapStyle fill:#fff3e0,stroke:#ff9800,stroke-width:2px,color:#e65100; classDef codeStyle fill:#f5f5f5,stroke:#9e9e9e,stroke-dasharray: 5 5,color:#333; classDef noteStyle fill:#e8f5e9,stroke:#4caf50,stroke-width:1px,color:#1b5e20; %% 顶部代码展示 Code["代码:Person p2 = p1;"]:::codeStyle subgraph Memory ["内存布局 (引用拷贝)"] direction LR subgraph Stack ["栈内存 (Stack)"] P1["p1 = 0x100"]:::stackStyle P2["p2 = 0x100"]:::stackStyle end subgraph Heap ["堆内存 (Heap)"] Object["Person 对象
name = '张三'
age = 20
地址: 0x100"]:::heapStyle end %% 引用指向 P1 ==> Object P2 ==> Object end %% 特点描述 Features["特点说明:
• 没有创建新对象
• 两个引用指向同一个内存地址
• 修改 p1 会同步反映在 p2 上"]:::noteStyle %% 布局辅助 Code ~~~ Memory Memory ~~~ Features ``` ### **2.2 代码示例** ```java public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } // Getter 和 Setter public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{name='" + name + "', age=" + age + "}"; } } /** * 引用拷贝测试 */ public class ReferenceCopyDemo { public static void main(String[] args) { Person p1 = new Person("张三", 20); // ===== 引用拷贝 ===== Person p2 = p1; // 只是复制了引用地址 System.out.println("===== 修改前 ====="); System.out.println("p1: " + p1); System.out.println("p2: " + p2); System.out.println("p1 == p2: " + (p1 == p2)); // true // 通过 p2 修改 p2.setAge(25); p2.setName("李四"); System.out.println("\n===== 通过 p2 修改后 ====="); System.out.println("p1: " + p1); // p1 也变了! System.out.println("p2: " + p2); } } ``` **输出结**果: ``` ===== 修改前 ===== p1: Person{name='张三', age=20} p2: Person{name='张三', age=20} p1 == p2: true ===== 通过 p2 修改后 ===== p1: Person{name='李四', age=25} p2: Person{name='李四', age=25} ``` --- ## 三、浅拷贝 ### **3.1 概念图解** ```mermaid %%{init: { "theme": "base", "themeVariables": { "primaryColor": "#e3f2fd", "primaryTextColor": "#0d47a1", "primaryBorderColor": "#2196f3", "lineColor": "#546e7a", "fontSize": "14px", "tertiaryColor": "#f5f5f5" }, "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true } }}%% graph LR %% 定义样式 classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1; classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c; classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100; classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20; subgraph Stack ["栈内存 (Stack)"] P1_Ref["p1 = 0x100"] P2_Ref["p2 = 0x200"] end subgraph Heap ["堆内存 (Heap)"] subgraph Object1 ["Person 对象 (0x100)"] P1_Data["name: '张三'
age: 20
address: 0x300"] end subgraph Object2 ["Person 对象 (0x200)"] P2_Data["name: '张三'
age: 20
address: 0x300"] end Addr_Obj[("Address 对象 (0x300)
city: '北京'")] end %% 连线关系 P1_Ref ==> Object1 P2_Ref ==> Object2 P1_Data -. "引用共享" .-> Addr_Obj P2_Data -. "引用共享" .-> Addr_Obj %% 注释说明 Note1["浅拷贝特点
1. 创建了新对象实例
2. 基本类型值复制
3. 引用类型仅复制地址"] %% 应用样式 class P1_Ref,P2_Ref main; class Addr_Obj storage; class Note1 term; class Object1,Object2 decision; %% 布局辅助 Note1 ~~~ Stack ``` ### **3.2 实现方式:Cloneable 接口** ```java /** * 地址类(引用类型属性) */ public class Address { private String city; private String street; public Address(String city, String street) { this.city = city; this.street = street; } // Getter 和 Setter public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } @Override public String toString() { return "Address{city='" + city + "', street='" + street + "'}"; } } /** * Person 类实现浅拷贝 */ public class Person implements Cloneable { private String name; // String 是不可变对象,特殊处理 private int age; // 基本类型 private Address address; // 引用类型 public Person(String name, int age, Address address) { this.name = name; this.age = age; this.address = address; } /** * 浅拷贝实现 */ @Override public Person clone() { try { return (Person) super.clone(); // Object.clone() 是浅拷贝 } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } // Getter 和 Setter public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @Override public String toString() { return "Person{name='" + name + "', age=" + age + ", address=" + address + "}"; } } ``` ### **3.3 浅拷贝测试** ```java public class ShallowCopyDemo { public static void main(String[] args) { // 创建原始对象 Address address = new Address("北京", "长安街"); Person p1 = new Person("张三", 20, address); // ===== 浅拷贝 ===== Person p2 = p1.clone(); System.out.println("===== 拷贝后初始状态 ====="); System.out.println("p1: " + p1); System.out.println("p2: " + p2); System.out.println("p1 == p2: " + (p1 == p2)); // false(不同对象) System.out.println("p1.address == p2.address: " + (p1.getAddress() == p2.getAddress())); // true(共享) // ===== 测试 1:修改基本类型属性 ===== p2.setAge(25); System.out.println("\n===== 修改 p2 的 age 后 ====="); System.out.println("p1.age: " + p1.getAge()); // 20(不受影响) System.out.println("p2.age: " + p2.getAge()); // 25 // ===== 测试 2:修改引用类型属性的内容 ===== p2.getAddress().setCity("上海"); System.out.println("\n===== 修改 p2 的 address.city 后 ====="); System.out.println("p1.address: " + p1.getAddress()); // 上海(被影响!) System.out.println("p2.address: " + p2.getAddress()); // 上海 // ===== 测试 3:替换整个引用 ===== p2.setAddress(new Address("广州", "天河路")); System.out.println("\n===== 替换 p2 的整个 address 后 ====="); System.out.println("p1.address: " + p1.getAddress()); // 上海(不受影响) System.out.println("p2.address: " + p2.getAddress()); // 广州 } } ``` **输出结**果: ``` ===== 拷贝后初始状态 ===== p1: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}} p2: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}} p1 == p2: false p1.address == p2.address: true ===== 修改 p2 的 age 后 ===== p1.age: 20 p2.age: 25 ===== 修改 p2 的 address.city 后 ===== p1.address: Address{city='上海', street='长安街'} p2.address: Address{city='上海', street='长安街'} ===== 替换 p2 的整个 address 后 ===== p1.address: Address{city='上海', street='长安街'} p2.address: Address{city='广州', street='天河路'} ``` ### **3.4 Object.clone() 源码分析** ``` /** * Object 类中的 clone 方法(native 方法) */ protected native Object clone() throws CloneNotSupportedException; ``` ```mermaid %%{init: { "theme": "base", "themeVariables": { "primaryColor": "#e3f2fd", "primaryTextColor": "#0d47a1", "primaryBorderColor": "#2196f3", "lineColor": "#546e7a", "fontSize": "14px", "tertiaryColor": "#f5f5f5" }, "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true } }}%% flowchart TB %% 样式定义 classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1; classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100; classDef error fill:#ffebee,stroke:#f44336,stroke-width:1.5px,color:#b71c1c; classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20; classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c; Start(["开始调用 Object.clone()"]) --> CheckInterface{"是否实现
Cloneable 接口?"} %% 异常分支 CheckInterface -- 否 --> ThrowEx[/"抛出 CloneNotSupportedException"/] class ThrowEx error %% 正常流程 CheckInterface == 是 ==> Allocate["创建新对象
(分配内存空间)"] class Allocate main Allocate ==> FieldCopy[["执行字段复制 (Field Copy)"]] subgraph CopyDetail [" 字段复制机制 (浅拷贝) "] direction TB Primitive["基本类型
(int, double, boolean...)"] -- 直接复制值 --> Value["新旧对象值相同"] Reference["引用类型
(对象、数组)"] -- 复制引用地址 --> Address["指向堆中同一个对象"] end FieldCopy --- CopyDetail CopyDetail ==> Return(["返回新对象的引用"]) class Return term %% 节点样式应用 class CheckInterface decision class FieldCopy main class Primitive,Reference storage ``` --- ## 四、深拷贝 ### **4.1 概念图解** ```mermaid %%{init: { "theme": "base", "themeVariables": { "primaryColor": "#e3f2fd", "primaryTextColor": "#0d47a1", "primaryBorderColor": "#2196f3", "lineColor": "#546e7a", "fontSize": "14px", "tertiaryColor": "#f5f5f5" }, "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true } }}%% flowchart LR %% 样式定义 classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1; classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c; classDef highlight fill:#fff3e0,stroke:#ff9800,stroke-width:2px,color:#e65100; %% 栈内存区域 subgraph Stack ["栈内存 (Stack)"] P1_Ref["p1 = 0x100"] P2_Ref["p2 = 0x200"] end %% 堆内存区域 subgraph Heap ["堆内存 (Heap)"] %% P1 的对象结构 subgraph P1_Area ["原始对象 P1"] P1_Obj["Person 对象 (0x100)
name: '张三'
age: 20"] P1_Addr_Ref["address (指向 0x300)"] end %% P2 的对象结构 subgraph P2_Area ["克隆对象 P2"] P2_Obj["Person 对象 (0x200)
name: '张三'
age: 20"] P2_Addr_Ref["address (指向 0x400)"] end %% Address 对象 Addr1[("Address 对象 (0x300)
city: '北京'")] Addr2[("Address 对象 (0x400)
city: '北京'")] end %% 逻辑连接 P1_Ref ==> P1_Obj P2_Ref ==> P2_Obj P1_Obj --- P1_Addr_Ref P1_Addr_Ref --> Addr1 P2_Obj --- P2_Addr_Ref P2_Addr_Ref --> Addr2 %% 独立性说明 Status{"完全独立"} Addr1 -.-> Status Addr2 -.-> Status %% 应用样式 class P1_Ref,P2_Ref main; class Addr1,Addr2 storage; class Status highlight; %% 标注 Note1["代码:Person p2 = p1.deepClone();"] Note1 ~~~ Stack ``` ### **4.2 实现方式一:手动递归拷贝** ```java /** * Address 类 - 支持深拷贝 */ public class Address implements Cloneable { private String city; private String street; public Address(String city, String street) { this.city = city; this.street = street; } /** * Address 自己的 clone 方法 */ @Override public Address clone() { try { return (Address) super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } // Getter/Setter/toString 省略 public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } @Override public String toString() { return "Address{city='" + city + "', street='" + street + "'}"; } } /** * Person 类 - 实现深拷贝 */ public class Person implements Cloneable { private String name; private int age; private Address address; public Person(String name, int age, Address address) { this.name = name; this.age = age; this.address = address; } /** * 深拷贝实现:递归调用内部对象的 clone */ @Override public Person clone() { try { Person cloned = (Person) super.clone(); // 关键:对引用类型属性也进行拷贝 if (this.address != null) { cloned.address = this.address.clone(); } return cloned; } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } // Getter/Setter 省略 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @Override public String toString() { return "Person{name='" + name + "', age=" + age + ", address=" + address + "}"; } } ``` ### **4.3 深拷贝测试** ```java public class DeepCopyDemo { public static void main(String[] args) { // 创建原始对象 Address address = new Address("北京", "长安街"); Person p1 = new Person("张三", 20, address); // ===== 深拷贝 ===== Person p2 = p1.clone(); System.out.println("===== 拷贝后初始状态 ====="); System.out.println("p1: " + p1); System.out.println("p2: " + p2); System.out.println("p1 == p2: " + (p1 == p2)); System.out.println("p1.address == p2.address: " + (p1.getAddress() == p2.getAddress())); // ===== 修改 p2 的 address.city ===== p2.getAddress().setCity("上海"); System.out.println("\n===== 修改 p2 的 address.city 后 ====="); System.out.println("p1.address: " + p1.getAddress()); // 北京(不受影响!) System.out.println("p2.address: " + p2.getAddress()); // 上海 } } ``` **输出结果**: ``` ===== 拷贝后初始状态 ===== p1: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}} p2: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}} p1 == p2: false p1.address == p2.address: false ===== 修改 p2 的 address.city 后 ===== p1.address: Address{city='北京', street='长安街'} p2.address: Address{city='上海', street='长安街'} ``` ### **4.4 实现方式二:序列化方式(推荐)** ```java import java.io.*; /** * 使用序列化实现深拷贝 */ public class DeepCopyUtil { /** * 通过序列化实现深拷贝 * 要求:对象及其所有属性都必须实现 Serializable 接口 */ @SuppressWarnings("unchecked") public static T deepCopy(T object) { try { // 1. 将对象写入字节流 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(object); oos.close(); // 2. 从字节流读取对象 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); T copy = (T) ois.readObject(); ois.close(); return copy; } catch (IOException | ClassNotFoundException e) { throw new RuntimeException("深拷贝失败", e); } } } /** * 实体类需要实现 Serializable */ public class Address implements Serializable { private static final long serialVersionUID = 1L; private String city; private String street; // ... 其他代码 } public class Person implements Serializable { private static final long serialVersionUID = 1L; private String name; private int age; private Address address; // ... 其他代码 } /** * 使用示例 */ public class SerializationDeepCopyDemo { public static void main(String[] args) { Address address = new Address("北京", "长安街"); Person p1 = new Person("张三", 20, address); // 深拷贝 Person p2 = DeepCopyUtil.deepCopy(p1); System.out.println("p1.address == p2.address: " + (p1.getAddress() == p2.getAddress())); // false(完全独立) p2.getAddress().setCity("上海"); System.out.println("p1.address.city: " + p1.getAddress().getCity()); // 北京 System.out.println("p2.address.city: " + p2.getAddress().getCity()); // 上海 } } ``` ### **4.5 实现方式三:JSON 序列化(第三方库)** ```java import com.google.gson.Gson; // 或者 import com.fasterxml.jackson.databind.ObjectMapper; /** * 使用 Gson 实现深拷贝 */ public class JsonDeepCopy { private static final Gson gson = new Gson(); public static T deepCopy(T object, Class clazz) { String json = gson.toJson(object); return gson.fromJson(json, clazz); } } /** * 使用 Jackson 实现深拷贝 */ public class JacksonDeepCopy { private static final ObjectMapper mapper = new ObjectMapper(); public static T deepCopy(T object, Class clazz) { try { String json = mapper.writeValueAsString(object); return mapper.readValue(json, clazz); } catch (Exception e) { throw new RuntimeException(e); } } } // 使用示例 Person p2 = JsonDeepCopy.deepCopy(p1, Person.class); ``` ### **4.6 深拷贝实现方式对比** | **实现方式** | **优点** | **缺点** | **适用场景** | | --- | --- | --- | --- | | **手动递归** | 性能最好,可定制 | 代码量大,易遗漏 | 简单对象 | | **序列化** | 通用,自动处理嵌套 | 性能较差,需实现 Serializable | 复杂对象 | | **JSON** | 简单,无需特殊接口 | 性能一般,需引入依赖 | 与前端交互的对象 | | **拷贝构造器** | 直观,可控 | 每个类都要写 | 明确需要拷贝的类 | --- --- ## 五、三种拷贝对比 ### **5.1 完整对比图** ```mermaid %%{init: { "theme": "base", "themeVariables": { "primaryColor": "#e3f2fd", "primaryTextColor": "#0d47a1", "primaryBorderColor": "#2196f3", "lineColor": "#546e7a", "fontSize": "14px", "tertiaryColor": "#f5f5f5" }, "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true } }}%% flowchart TB %% 样式定义 classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1; classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100; classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20; classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c; classDef note fill:#fafafa,stroke:#9e9e9e,stroke-dasharray: 5 5; subgraph RefCopy ["引用拷贝 (Reference Copy)"] direction LR R_p1["p1 (引用)"] R_p2["p2 (引用)"] R_Obj1[["Person 对象"]] R_Addr1[("Address 对象")] R_p1 --> R_Obj1 R_p2 --> R_Obj1 R_Obj1 -- "address 属性" --> R_Addr1 R_Note["✗ 没有创建新对象
✗ 修改任何属性都互相影响"] class R_Note note end subgraph ShallowCopy ["浅拷贝 (Shallow Copy)"] direction LR S_p1["p1 (引用)"] S_p2["p2 (引用)"] S_Obj1[["Person 对象 (原)"]] S_Obj2[["Person 对象 (新)"]] S_Addr1[("Address 对象 (共享)")] S_p1 --> S_Obj1 S_p2 --> S_Obj2 S_Obj1 -- "address" --> S_Addr1 S_Obj2 -- "address" --> S_Addr1 S_Note["✓ 创建了新 Person 对象
✓ 基本类型独立
✗ 引用类型属性共享"] class S_Note note end subgraph DeepCopy ["深拷贝 (Deep Copy)"] direction LR D_p1["p1 (引用)"] D_p2["p2 (引用)"] D_Obj1[["Person 对象 (原)"]] D_Obj2[["Person 对象 (新)"]] D_Addr1[("Address 对象 (原)")] D_Addr2[("Address 对象 (新)")] D_p1 --> D_Obj1 D_p2 --> D_Obj2 D_Obj1 -- "address" --> D_Addr1 D_Obj2 -- "address" --> D_Addr2 D_Note["✓ 所有属性完全独立
✓ 递归复制引用对象
✓ 完全互不影响"] class D_Note note end %% 应用样式 class R_p1,R_p2,S_p1,S_p2,D_p1,D_p2 main class R_Obj1,S_Obj1,S_Obj2,D_Obj1,D_Obj2 decision class R_Addr1,S_Addr1,D_Addr1,D_Addr2 storage ``` ### **5.2 修改影响对比表** | **操作** | **引用拷贝** | **浅拷贝** | **深拷贝** | | --- | --- | --- | --- | | 修改 p2.age(基本类型) | p1 受影响 | p1 不受影响 | p1 不受影响 | | 修改 p2.name(String,不可变) | p1 受影响 | p1 不受影响\* | p1 不受影响 | | 修改 p2.address.city | p1 受影响 | **p1 受影响** | p1 不受影响 | | 替换 p2.address = new Address() | p1 受影响 | p1 不受影响 | p1 不受影响 | > *\*注:String 是不可变对象,重新赋值会创建新对象,所以表现得像深拷贝。* --- ### **5.3 综合测试代码** ```java public class CopyComparisonDemo { public static void main(String[] args) { System.out.println("========== 1. 引用拷贝 =========="); testReferenceCopy(); System.out.println("\n========== 2. 浅拷贝 =========="); testShallowCopy(); System.out.println("\n========== 3. 深拷贝 =========="); testDeepCopy(); } static void testReferenceCopy() { Person p1 = new Person("张三", 20, new Address("北京", "长安街")); Person p2 = p1; // 引用拷贝 p2.getAddress().setCity("上海"); System.out.println("修改 p2.address.city 后:"); System.out.println("p1.address.city = " + p1.getAddress().getCity()); // 上海 System.out.println("p2.address.city = " + p2.getAddress().getCity()); // 上海 System.out.println("结论: p1 受影响"); } static void testShallowCopy() { Person p1 = new Person("张三", 20, new Address("北京", "长安街")); Person p2 = p1.shallowClone(); // 浅拷贝 p2.getAddress().setCity("上海"); System.out.println("修改 p2.address.city 后:"); System.out.println("p1.address.city = " + p1.getAddress().getCity()); // 上海 System.out.println("p2.address.city = " + p2.getAddress().getCity()); // 上海 System.out.println("结论: p1 受影响(共享内部对象)"); } static void testDeepCopy() { Person p1 = new Person("张三", 20, new Address("北京", "长安街")); Person p2 = p1.deepClone(); // 深拷贝 p2.getAddress().setCity("上海"); System.out.println("修改 p2.address.city 后:"); System.out.println("p1.address.city = " + p1.getAddress().getCity()); // 北京 System.out.println("p2.address.city = " + p2.getAddress().getCity()); // 上海 System.out.println("结论: p1 不受影响(完全独立)"); } } ``` --- ## 六、复杂场景:多层嵌套 ### **6.1 多层嵌套对象** ```java /** * 公司类(多层嵌套示例) */ public class Company implements Serializable, Cloneable { private String name; private Address headquarters; // 第1层嵌套 private List departments; // 集合嵌套 // 深拷贝(手动实现) @Override public Company clone() { try { Company cloned = (Company) super.clone(); // 拷贝 Address if (this.headquarters != null) { cloned.headquarters = this.headquarters.clone(); } // 拷贝 List if (this.departments != null) { cloned.departments = new ArrayList<>(); for (Department dept : this.departments) { cloned.departments.add(dept.clone()); // 每个元素都要 clone } } return cloned; } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } } /** * 部门类 */ public class Department implements Serializable, Cloneable { private String name; private List employees; // 第2层嵌套 @Override public Department clone() { try { Department cloned = (Department) super.clone(); if (this.employees != null) { cloned.employees = new ArrayList<>(); for (Employee emp : this.employees) { cloned.employees.add(emp.clone()); } } return cloned; } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } } ``` ### **6.2 多层嵌套图示** ```mermaid %%{init: { "theme": "base", "themeVariables": { "primaryColor": "#e3f2fd", "primaryTextColor": "#0d47a1", "primaryBorderColor": "#2196f3", "lineColor": "#546e7a", "fontSize": "14px", "tertiaryColor": "#f5f5f5" }, "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true } }}%% flowchart TB subgraph ShallowCopy ["浅拷贝 (Shallow Copy) - 仅复制顶层"] direction LR S_Orig["原对象 Company"] S_Addr["Address 对象"] S_List["List 集合"] S_Dept["Department 对象"] S_Emp["Employee 对象"] S_New["新对象 Company"] S_Orig --> S_Addr S_Orig --> S_List S_List --> S_Dept S_Dept --> S_Emp S_New == "引用相同地址" ==> S_Addr S_New == "引用相同地址" ==> S_List end subgraph DeepCopy ["深拷贝 (Deep Copy) - 递归复制所有层级"] direction TB subgraph OriginalTree ["原始对象树"] direction LR O_Comp["Company"] --> O_Addr["Address"] O_Addr --> O_List["List"] O_List --> O_Dept["Department"] O_Dept --> O_Emp["Employee"] end subgraph NewTree ["全新副本树"] direction LR N_Comp["Company"] --> N_Addr["Address"] N_Addr --> N_List["List"] N_List --> N_Dept["Department"] N_Dept --> N_Emp["Employee"] end O_Comp -. "独立副本" .-> N_Comp O_Addr -. "独立副本" .-> N_Addr O_List -. "独立副本" .-> N_List O_Dept -. "独立副本" .-> N_Dept O_Emp -. "独立副本" .-> N_Emp end subgraph Tips ["💡 最佳实践"] T1["复杂对象推荐使用序列化/反序列化 (JSON/Protobuf)"] T2["手动实现需注意循环引用问题"] end %% 样式定义 classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1; classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100; classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20; classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c; class S_New,N_Comp,N_Addr,N_List,N_Dept,N_Emp main; class S_Orig,O_Comp,O_Addr,O_List,O_Dept,O_Emp storage; class T1,T2 decision; ``` --- ## 七、特殊情况处理 ### **7.1 不可变对象** ```mermaid %%{init: { "theme": "base", "themeVariables": { "primaryColor": "#e3f2fd", "primaryTextColor": "#0d47a1", "primaryBorderColor": "#2196f3", "lineColor": "#546e7a", "fontSize": "14px", "tertiaryColor": "#f5f5f5" }, "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true } }}%% flowchart TB subgraph Core ["不可变对象核心逻辑"] direction TB ObjType(["不可变对象 (Immutable Objects)"]) Examples["String, Integer, LocalDate"] Features{{"核心特点"}} F1["创建后状态不可改变"] F2["修改操作 = 返回新对象"] Strategy{{"拷贝处理策略"}} S1["直接引用共享 (Shallow Share)"] S2["无需深拷贝 (Deep Copy Not Needed)"] end subgraph Example ["内存变化示例: String name = '张三'"] direction LR State1["栈变量: name"] -- "初始指向" --> Val1[("堆内存: '张三'")] Update["执行: name = '李四'"] State1 == "重定向" ==> Val2[("堆内存: '李四'")] Val1 -. "原对象保持不变" .-> Val1 end %% 节点连接 ObjType --- Examples Examples --> Features Features --> F1 Features --> F2 F1 & F2 --> Strategy Strategy --> S1 Strategy --> S2 S1 ==> Example %% 样式定义 classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1; classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100; classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20; classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c; class ObjType,Examples main; class Features,Strategy decision; class F1,F2,S1,S2 term; class Val1,Val2 storage; ``` ### **7.2 数组的拷贝** ```java public class ArrayCopyDemo { public static void main(String[] args) { // ===== 一维基本类型数组 ===== int[] arr1 = {1, 2, 3}; int[] arr2 = arr1.clone(); // 深拷贝 arr2[0] = 100; System.out.println(arr1[0]); // 1(不受影响) // ===== 一维引用类型数组 ===== Person[] persons1 = {new Person("张三", 20, null)}; Person[] persons2 = persons1.clone(); // 浅拷贝! persons2[0].setName("李四"); System.out.println(persons1[0].getName()); // 李四(受影响!) // ===== 二维数组 ===== int[][] matrix1 = {{1, 2}, {3, 4}}; int[][] matrix2 = matrix1.clone(); // 浅拷贝! matrix2[0][0] = 100; System.out.println(matrix1[0][0]); // 100(受影响!) // ===== 二维数组深拷贝 ===== int[][] matrix3 = new int[matrix1.length][]; for (int i = 0; i < matrix1.length; i++) { matrix3[i] = matrix1[i].clone(); // 每行单独 clone } } } ``` **数组拷贝总结**: | **数组类型** | `clone()` **/** `Arrays.copyOf()` | **效果** | | --- | --- | --- | | 一维基本类型 | 深拷贝 | ✅ 独立 | | 一维引用类型 | 浅拷贝 | ⚠️ 元素共享 | | 二维数组 | 浅拷贝 | ⚠️ 行数组共享 | --- ## 八、最佳实践与总结 ### **8.1 选择建议** ```mermaid %%{init: { "theme": "base", "themeVariables": { "primaryColor": "#e3f2fd", "primaryTextColor": "#0d47a1", "primaryBorderColor": "#2196f3", "lineColor": "#546e7a", "fontSize": "14px", "tertiaryColor": "#f5f5f5" }, "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true } }}%% graph TB %% 样式定义 classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1; classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100; classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20; classDef highlight fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c; subgraph SelectionGuide ["对象拷贝选择建议"] direction TB Start(["开始判断"]) --> Q1{"需要拷贝对象吗?"} Q1 -- "只读使用" --> Result1["引用拷贝
(无需物理拷贝)"] Q1 -- "需要修改" --> Q2{"对象包含引用属性?"} Q2 -- "没有" --> Result2["浅拷贝
(Shallow Copy)"] Q2 -- "有" --> Q3{"内部引用也需要
独立修改吗?"} Q3 -- "否" --> Result3["浅拷贝"] Q3 -- "是" --> Result4["深拷贝
(Deep Copy)"] end %% 节点分类应用 class Start main; class Q1,Q2,Q3 decision; class Result1,Result2,Result3 term; class Result4 highlight; %% 核心路径加粗 Q2 == "有" ==> Q3 Q3 == "是" ==> Result4 %% 补充说明样式 style SelectionGuide fill:#fcfcfc,stroke:#d1d1d1,stroke-dasharray: 5 5; ``` ### **8.2 实现方式选择** | **场景** | **推荐方式** | **原因** | | --- | --- | --- | | 简单对象,无嵌套 | 手动 clone | 性能最好 | | 复杂对象,多层嵌套 | 序列化 | 自动处理所有层级 | | 需要与前端交互 | JSON | 一举两得 | | 防御性拷贝 | 拷贝构造器 | 代码直观 | | 集合拷贝 | Stream + 深拷贝 | 灵活控制 | --- ### **8.3 防御性拷贝** ```java /** * 防御性拷贝:保护内部状态不被外部修改 */ public class ImmutablePerson { private final String name; private final Date birthDate; // Date 是可变的! public ImmutablePerson(String name, Date birthDate) { this.name = name; // 防御性拷贝:复制传入的参数 this.birthDate = new Date(birthDate.getTime()); } public Date getBirthDate() { // 防御性拷贝:返回副本而非原对象 return new Date(birthDate.getTime()); } } ``` ### **8.4 速查表** | **对比项** | **引用拷贝** | **浅拷贝** | **深拷贝** | | --- | --- | --- | --- | | 新对象 | ❌ | ✅ | ✅ | | 基本类型独立 | ❌ | ✅ | ✅ | | 引用类型独立 | ❌ | ❌ | ✅ | | 实现难度 | 无 | 简单 | 复杂 | | 性能 | 最快 | 快 | 较慢 | --- ### **8.5 记忆口诀** ```mermaid %%{init: { "theme": "base", "themeVariables": { "primaryColor": "#e3f2fd", "primaryTextColor": "#0d47a1", "primaryBorderColor": "#2196f3", "lineColor": "#546e7a", "fontSize": "14px", "tertiaryColor": "#f5f5f5" }, "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true } }}%% flowchart TB %% 核心分类 Root(["Java/JS 对象拷贝记忆口诀"]) subgraph RefGroup ["引用拷贝 (Reference Copy)"] direction TB R1["复制地址,同一对象"] R2[["两个名字,一个人"]] end subgraph ShallowGroup ["浅拷贝 (Shallow Copy)"] direction TB S1["新皮旧馅,表面功夫"] S2["房子是新的,家具是共享的"] S3["基本类型复制值,引用类型复制地址"] end subgraph DeepGroup ["深拷贝 (Deep Copy)"] direction TB D1["彻底独立,完全分家"] D2["房子是新的,家具也全是新的"] D3["递归复制,层层独立"] end subgraph StrategyGroup ["选择口诀 (Strategy)"] direction LR ST1["只读引用,修改要拷贝"] ST2["简单浅拷贝,嵌套深拷贝"] ST3["序列化最省心,手动写最性能"] end %% 连接关系 Root ==> RefGroup Root ==> ShallowGroup Root ==> DeepGroup RefGroup ~~~ StrategyGroup ShallowGroup ==> StrategyGroup DeepGroup ==> StrategyGroup %% 样式定义 classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1; classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100; classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20; classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c; class Root main; class R1,R2 main; class S1,S2,S3 decision; class D1,D2,D3 term; class ST1,ST2,ST3 storage; ``` --- ### **8.6 核心要点图** ```mermaid %%{init: { "theme": "base", "themeVariables": { "primaryColor": "#e3f2fd", "primaryTextColor": "#0d47a1", "primaryBorderColor": "#2196f3", "lineColor": "#546e7a", "fontSize": "14px", "tertiaryColor": "#fdfdfd" }, "flowchart": { "curve": "basis", "htmlLabels": true } }}%% graph TB %% 核心分类 subgraph Core ["1. 本质区别 (Copy Types)"] Type1["引用拷贝
仅复制指针,指向同一内存地址"] Type2["浅拷贝
创建新对象,但内部引用仍共享"] Type3["深拷贝
递归复制,完全独立的副本"] end %% 实现路径 subgraph Implementation ["2. 实现方式 (Implementation)"] direction LR Method1[["Object.clone() 默认方式"]] subgraph DeepMethods ["深拷贝具体手段"] M2["手动递归 Clone"] M3["序列化 / 反序列化"] M4["JSON 转换"] M5["拷贝构造器"] end end %% 注意事项 subgraph Precautions ["3. 开发注意事项 (Best Practices)"] Note1("必须实现 Cloneable 接口") Note2("String 等不可变对象无需深拷贝") Note3("数组 clone 对引用元素仍是浅拷贝") Note4("复杂对象推荐序列化方式") end %% 逻辑连接 Type2 -.-> Method1 Type3 -.-> DeepMethods Method1 ==> Note1 DeepMethods ==> Note4 %% 样式定义 classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1; classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100; classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20; classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c; class Type1,Type2,Type3 main; class Method1,M2,M3,M4,M5 decision; class Note1,Note2,Note3,Note4 term; ```